home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
asm_n_z.zip
/
SWEEP.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-06-04
|
10KB
|
325 lines
; SWEEP.ASM -- Runs program or command across subdirectories
; =========
;
; (C) Copyright Charles Petzold, 1985
CSEG Segment
Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
Org 002Ch
Environment Label Byte ; Segment of Environment is here
Org 007Dh
NewParam Label Byte ; Parameter to pass to COMMAND
Org 0080h
OldParam Label Byte ; Parameter passed to SWEEP
Org 0100h
Entry: Jmp Begin ; SWEEP.COM Entry Point
; Most Data (some more at end of program)
; ---------
SweepMessage db 13,10,'>>> SWEEP >>> ' ; The SWEEP message
CurrentDir db ?,':\' ; ? gets drive letter
db '(C) Copyright Charles Petzold, 1985',1Ah
DosVersMsg db 'Needs DOS 2.0 +$' ; Error Messages
MemAllocMsg db 'Allocation Problem$'
CommandMsg db 'SWEEP: COMMAND Problem$'
AbnormalMsg db 'SWEEP: Abnormal Exit$'
DosVersion dw ? ; Store DOS Version Number here
BreakState db ? ; Store original break state here
Comspec db 'COMSPEC=' ; String for Environment search
CommandAsciiz dd ? ; Address of COMMAND.COM string
ParamBlock dw ? ; Parameter block for EXEC call
dw NewParam,?
dw 5Ch,?
dw 6Ch,?
SearchAsciiZ db '*.*',0 ; Asciiz for Find call
BackOneDir db '..',0 ; Asciiz for moving back one directory
DtaPointer dw DtaAreaBegin ; For nested directory searches
Direction db 0 ; Forward search initially
; Check DOS Version
; -----------------
Begin: Mov AH,30h ; Check for DOS Version
Int 21h
Cmp AL,2 ; See if it's 2.0 or above
Jae DosVersOK ; If so, we can proceed
Mov DX,Offset DosVersMsg ; Otherwise error message
ErrorExit: Mov AH,9 ; Print String function call
Int 21h ; Do it
Int 20h ; And exit prematurely
DosVersOK: Xchg AL,AH ; Get Major Version in AH
Mov [DosVersion],AX ; And save whole thing
; Un-allocate rest of memory
; --------------------------
Mov SP,Offset StackTop ; Set new stack pointer
Mov BX,Offset EndOfProgram ; This is beyond our needs
Mov CL,4 ; Prepare for shift
Shr BX,CL ; Convert to segment form
Mov AH,4Ah ; Shrink allocated memory
Int 21h ; By calling DOS
Jnc MemAllocOK ; If no error, we can proceed
Mov DX,Offset MemAllocMsg ; Otherwise set up for message
Jmp ErrorExit ; Print it and terminate
; Search for Comspec in Environment
; ---------------------------------
MemAllocOK: Push ES ; We'll be changing this
Mov BX,Offset Environment ; Segment of Environment
Mov ES,[BX] ; Set ES to it
Assume ES:Nothing ; And tell the assembler
Sub DI,DI ; Start at the beginning
Mov SI,Offset ComSpec ; String to search for
Cld ; Direction must be forward
TryThis: Cmp Byte Ptr ES:[DI],0 ; See if points to zero
Jz NoFindComSpec ; If so, we're dead in water
Push SI ; Temporarily save these
Push DI
Mov CX,8 ; Search string has 8 chars
Repz Cmpsb ; Do the string compare
Pop DI ; Get back the registers
Pop SI
Jz FoundComspec ; If equals, we've found it
Sub AL,AL ; Otherwise search for zero
Mov CX,-1 ; For 'infinite' bytes
Repnz Scasb ; Do the search
Jmp TryThis ; And try the next string
NoFindComSpec: Pop ES ; Get back ES on error
Mov DX,Offset CommandMsg ; Set up error message
Jmp ErrorExit ; And bow out gracefully
FoundComspec: Add DI,8 ; so points after 'COMSPEC='
Mov Word Ptr [CommandASCIIZ],DI ; Save the address
Mov Word Ptr [CommandASCIIZ + 2],ES ; including segment
; Set up parameter block for EXEC call
; ------------------------------------
Mov [ParamBlock],ES ; Segment of environment
Mov [ParamBlock + 4],CS ; Segment of parameter
Mov [ParamBlock + 8],CS ; Segment of 1st FCB
Mov [ParamBlock + 12],CS ; Segment of 2nd FCB
Pop ES ; Restores ES to this segment
Assume ES:CSEG ; And make sure MASM knows
; Fix up new paramater for "/C" String
; ------------------------------------
Mov AL,[OldParam] ; Get old character count
Add AL,3 ; Three more characters in paramater
Mov [NewParam],AL ; New number of characters
Mov [NewParam + 1],' ' ; Next is a blank
Mov Word Ptr [NewParam + 2],'C/' ; Then a /C
; Get the current break state, drive, and subdirectory
; ----------------------------------------------------
Mov AX,3300h ; Get Break State
Int 21h ; By calling DOS
Mov [BreakState],DL ; Save it
Sub DL,DL ; Set it to OFF
Mov AX,3301h ; Set Break State
Int 21h ; By calling DOS
Mov DX,Offset Terminate ; For Ctrl-Break exits
Mov AX,2523h ; Set Interrupt 23h vector
Int 21h ; through DOS call
Mov AH,19h ; Get current drive
Int 21h ; By calling DOS
Add AL,'A' ; Convert to letter
Mov [CurrentDir],AL ; And save it
Mov SI,Offset StartOffDir ; Repository of directory
Sub DL,DL ; Indicate default drive
Mov AH,47h ; Get current directory
Int 21h ; By calling DOS
; Display SWEEP message with current drive and subdirectory
; ---------------------------------------------------------
MainLoop: Mov SI,3 + Offset CurrentDir; Receives directory
Sub DL,DL ; Indicate current drive
Mov AH,47h ; Current directory call
Int 21h ; Get it
Mov SI,Offset SweepMessage ; String to display
Cld ; Want direction forward
DirPrintLoop: Lodsb ; Get the character
Or AL,AL ; Check if it's zero
Jz NoMoreDirPrint ; If so, branch out
Mov DL,AL ; Otherwise set DL to it
Mov AH,2 ; For Display Output
Int 21h ; Display the character
Jmp DirPrintLoop ; And loop around for the next
NoMoreDirPrint: Mov CX,500 ; We'll hang out here awhile
StatCheckLoop: Mov AH,0Bh ; Set up for keyboard status
Int 21h ; Allow user to Break out
Loop StatCheckLoop ; Do it a few more times
Cmp [DosVersion],30Ah ; See if DOS is 3.1 or higher
Jb LoadCommand ; If not, skip CR & LF
Mov DL,13 ; Carriage Return
Mov AH,2 ; Write to Display
Int 21h ; by calling DOS
Mov DL,10 ; Line Feed
Mov AH,2 ; Write to Display
Int 21h ; by calling DOS
; Load COMMAND.COM
; -----------------
LoadCommand: Mov BX,Offset ParamBlock ; ES:BX = parameter block
Lds DX,[CommandAsciiz] ; DS:DX = Asciiz of COMMAND
Sub AL,AL ; EXEC type zero
Mov AH,4Bh ; EXEC function call
Int 21h ; Load command processor
; Return from COMMAND.COM
; -----------------------
Mov AX,CS ; This is the current code segment
Mov DS,AX ; Reset DS to this segment
Mov ES,AX ; Reset ES to this segment
Mov SS,AX ; Reset stack segment to it
Mov SP,Offset StackTop ; And reset stack pointer also
; Avoid problems caused by commands that may change drive or directory
; --------------------------------------------------------------------
PushF ; Save EXEC Error Flag
Sub DL,DL ; Set Break State to OFF
Mov AX,3301h ; Set Break State
Int 21h ; By calling DOS
Mov DL,[CurrentDir] ; Get original drive letter
Sub DL,'A' ; Convert to number
Mov AH,0Eh ; Select disk
Int 21h ; Through DOS call
PopF ; Get back EXEC Error Flag
Mov DX,Offset CommandMsg ; Set up possible error message
Jc ErrorExit2 ; And print if EXEC error
Mov DX,2 + Offset CurrentDir; The pre-COMMAND directory
Mov AH,3Bh ; Call to change directory
Int 21h ; Do it
Jnc NextLevel ; Continue if no error
Mov DX,Offset AbnormalMsg ; Otherwise set up message
ErrorExit2: Mov AH,9 ; Will print the string
Int 21h ; Print it
Jmp Terminate ; And get out of here
; Find first or next subdirectory level
; -------------------------------------
NextLevel: Mov DX,[DTAPointer] ; Next nested DTA
Mov AH,1Ah ; For DOS call to set DTA
Int 21h ; Do it
Cmp [Direction],0 ; Check if we're nesting
Jnz FindNextFile ; If not, we're continuing
Mov DX,Offset SearchAsciiZ ; We search for *.*
Mov CX,10h ; Subdirectory attribute
Mov AH,4Eh ; Find first file
Int 21h ; by calling DOS
Jmp Short TestMatch ; Hop around next section
FindNextFile: Mov AH,4Fh ; Find next file
Int 21h ; by calling DOS
TestMat